<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>原生构造函数的继承</title>
</head>
<body>
    <h1>原生构造函数的继承</h1>

    <script>
        // 继承Array
        class MyArray extends Array {
            first() {
                return this[0];
            }

            last() {
                return this[this.length - 1];
            }
        }

        const arr = new MyArray(1, 2, 3);
        console.log(arr.first()); // 1
        console.log(arr.last()); // 3

        // 继承Error
        class ExtendableError extends Error {
            constructor(message) {
                super(message);
                this.name = this.constructor.name;
                if (typeof Error.captureStackTrace === 'function') {
                    Error.captureStackTrace(this, this.constructor);
                } else {
                    this.stack = (new Error(message)).stack;
                }
            }
        }

        class ValidationError extends ExtendableError {
            constructor(message) {
                super(message);
            }
        }

        // 使用自定义错误
        try {
            throw new ValidationError('验证失败');
        } catch (e) {
            console.log(e.name); // "ValidationError"
            console.log(e.message); // "验证失败"
            console.log(e instanceof ValidationError); // true
            console.log(e instanceof Error); // true
        }

        // 继承内置对象
        class VersionedArray extends Array {
            constructor() {
                super();
                this.history = [[]];
            }

            commit() {
                this.history.push([...this]);
            }

            revert() {
                const previousVersion = this.history[this.history.length - 2];
                if (previousVersion) {
                    this.splice(0, this.length, ...previousVersion);
                    this.history.pop();
                }
            }
        }

        const x = new VersionedArray();
        x.push(1);
        x.push(2);
        x.commit();
        x.push(3);
        console.log(x); // [1, 2, 3]
        x.revert();
        console.log(x); // [1, 2]
    </script>
</body>
</html> 